package com.client.service;

import com.client.entity.B_client;
import com.client.entity.PassAuthor;
import com.client.mapper.MessageDao;
import com.client.mapper.PassAuthorDao;
import com.client.sm9.gm.sm9.G1KeyPair;
import com.client.sm9.gm.sm9.ResultSignature;
import com.client.utils.AESutil;
import com.client.utils.MessageUtils;
import com.client.utils.UDPUtil;
import com.client.utils.Utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Service
//计算迁移请求发送
public class MigrationService {

    @Autowired
    PassAuthorDao passAuthorDao;
    @Autowired
    KeyService keyService;
    @Autowired
    UDPUtil udp;
    @Autowired
    MessageDao messageDao;

    String HPS = "HPS";

    PassAuthor hps;

    //加密
    public void Encrypt(String id, UUID uid, byte[] msg) {
        hps = passAuthorDao.queryByName("HPS");
        Map<String, Object> map = mapinit();
        map.put("goal_id", id);
        map.put("msg", msg);
        map.put("uid", uid);
        map.put("type", "MIGRATION_ENCRYPT");
        UUID MessageUUID = MessageUtils.getuuid();
        byte[] bytes = mapdeal(map, hps.getK(), MessageUUID);
        addMessage(hps, MessageUtils.getuuid().toString(), bytes,
                MessageUUID.toString(), (String) map.get("type"));
    }

    //解密
    public void Decrypt(byte[] msg) {
        hps = passAuthorDao.queryByName("HPS");
        Map<String, Object> map = mapinit();
        map.put("my_id", keyService.getId());
        map.put("msg", msg);
        map.put("de", Utils.serializePrivateKey(keyService.getDe()));
        map.put("uid", MessageUtils.getuuid());
        map.put("type", "MIGRATION_DECRYPT");
        UUID MessageUUID = MessageUtils.getuuid();
        byte[] bytes = mapdeal(map, hps.getK(), MessageUUID);
        addMessage(hps, MessageUtils.getuuid().toString(), bytes,
                MessageUUID.toString(), (String) map.get("type"));
    }

    //签名
    public void Sign(byte[] msg, UUID uid) {
        hps = passAuthorDao.queryByName("HPS");
        Map<String, Object> map = mapinit();
        map.put("uid", uid);
        map.put("my_id", keyService.getId());
        map.put("msg", msg);
        map.put("ds", Utils.serializePrivateKey(keyService.getDs()));
        map.put("type", "MIGRATION_SIGN");
        UUID MessageUUID = MessageUtils.getuuid();
        byte[] bytes = mapdeal(map, hps.getK(), MessageUUID);
        addMessage(hps, uid.toString(), bytes,
                MessageUUID.toString(), (String) map.get("type"));
    }

    //验签
    public void Verify(String goal_id, UUID uid, byte[] msg, ResultSignature signature) {
        hps = passAuthorDao.queryByName("HPS");
        Map<String, Object> map = mapinit();
        map.put("goal_id", goal_id);
        map.put("uid", uid);
        map.put("msg", msg);
        map.put("signature", Utils.serializeResultSignature(signature));
        map.put("type", "MIGRATION_VERIFY");
        UUID MessageUUID = MessageUtils.getuuid();
        byte[] bytes = mapdeal(map, hps.getK(), MessageUUID);
        addMessage(hps, uid.toString(), bytes,
                MessageUUID.toString(), (String) map.get("type"));
    }

    //密钥交换1
    public void Exchange1(B_client client) {
        hps = passAuthorDao.queryByName("HPS");
        Map<String, Object> map = mapinit();
        map.put("goal_id", client.getGoal_id());
        map.put("uid", client.getUid());
        map.put("type", "MIGRATION_EXCHANGE_ONE");
        UUID MessageUUID = MessageUtils.getuuid();
        byte[] bytes = mapdeal(map, hps.getK(), MessageUUID);
        addMessage(hps, client.getUid().toString(), bytes,
                MessageUUID.toString(), (String) map.get("type"));
    }

    //密钥交换2
    public void Exchange2(String goal_id, UUID uid, boolean isSonsor, int keyByteLen,
                          G1KeyPair myTempKeyPair, byte[] R) {
        hps = passAuthorDao.queryByName("HPS");
        Map<String, Object> map = mapinit();
        map.put("uid", uid);
        map.put("my_id", keyService.getId());
        map.put("goal_id", goal_id);
        map.put("isSonsor", isSonsor);
        map.put("keyByteLen", keyByteLen);
        map.put("R", R);
        map.put("myTempKeyPair", Utils.serializeG1KeyPair(myTempKeyPair));
        map.put("D_exchange", Utils.serializePrivateKey(keyService.getD_exchange()));
        map.put("type", "MIGRATION_EXCHANGE_TWO");
        UUID MessageUUID = MessageUtils.getuuid();
        byte[] bytes = mapdeal(map, hps.getK(), MessageUUID);
        addMessage(hps, uid.toString(), bytes,
                MessageUUID.toString(), (String) map.get("type"));
    }

    //初始化map
    public Map<String, Object> mapinit() {
        return new HashMap<>();
    }

    //map加密后附上id
    public byte[] mapdeal(Map<String, Object> map, byte[] k, UUID uuid) {
        Map<String, Object> result = new HashMap<>();

        result.put("id", keyService.getId());
        result.put("time", MessageUtils.getNowTime());
        result.put("uid", MessageUtils.getuuid());
        result.put("uuid", uuid);
        result.put("body", AESutil.encrypt(Utils.getByteFromObjectMap(map), k));
        result.put("hash", MessageUtils.HashOfFormal(result, k));

        byte[] bytes = Utils.getByteFromObjectMap(result);
        //添加到消息
        Date time = MessageUtils.getNowTime();
        MessageService.addMessage(result.get("uid").toString(), hps.getIp(), hps.getPort(), bytes,
                time, 8, 30);
        messageDao.add(hps.getName(), keyService.getId(), hps.getIp(), hps.getPort(), result.get("uid").toString(), uuid.toString(),
                1, map.get("type").toString(), new Timestamp(time.getTime()));

        return bytes;
    }

    public void addMessage(PassAuthor hps, String uid, byte[] msg, String uuid, String type) {
        udp.send(hps.getIp(), hps.getPort(), msg);

    }
}
